package edu.cuit.avatar.thread;

import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author <a href="mailto:1020zhaodan@163.com">Adan</a>
 * @version 1.0
 * @date 2025/7/16 15:30
 */
public class QueueTask {
    private static Buffer buffer = new Buffer();
    /**
     * 缓冲去存储的工作任务
     */
    private static class Task{
        private String id;

        public Task() {
            this.id = UUID.randomUUID().toString();
        }

        @Override
        public String toString() {
            return "Task["  + id + "]";
        }
    }

    /**
     * 用于存储Task的缓冲区(缓冲区的大小是受限的)
     *      write(Task task): void将一个Task实例添加到缓冲区
     *      read(): Task 从缓冲区中读取和删除一个task
     */
    private static class Buffer{
        //缓冲区的大小
        private static final int CAPACITY = 10;

        private Lock lock = new ReentrantLock(true);
        private Condition notFull = lock.newCondition();
        private Condition notEmpty = lock.newCondition();

        private Queue<Task> buffer = new LinkedList<>();

        public void write(Task task){
            try {
                lock.lock();
                //判断缓冲区未满
                while (buffer.size() == CAPACITY) {
                    //让当前任务进行等待
                    System.out.println("wait for notFull condition");
                    notFull.await();
                }
                buffer.offer(task);
                // 每添加一个Task实例,尝试唤醒notEmpty条件任务
                notEmpty.signal();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
        }

        public Task read(){
            Task task = null;
            try {
                lock.lock();
                //判断缓冲区非空
                while (buffer.size() == 0) {
                    //让当前任务进行等待
                    System.out.println("wait for notEmpty condition");
                    notEmpty.await();
                }
                task = buffer.poll();
                // 每删除一个Task实例,尝试唤醒notFull条件任务
                notFull.signal();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
            return task;
        }
    }

    /**
     * 生产者:不停向Buffer缓冲区添加Task实例
     */
    public static class Producer implements Runnable{
        @Override
        public void run() {
            try {
                while(true){
                    var task = new Task();
                    buffer.write(task);
                    System.out.println("Producer[" + Thread.currentThread().getName() + "] put " + task);
                    Thread.sleep((int) (Math.random() * 100));
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 消费者:不停从Buffer缓冲区删除Task实例
     */
    public static class Customer implements Runnable{
        @Override
        public void run() {
            try {
                while(true){

                    var task = buffer.read();
                    System.err.println("Consumer[" + Thread.currentThread().getName() + "] got " + task);
                    Thread.sleep((int) (Math.random() * 100));
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static void main(String[] args) {
        var executor = Executors.newFixedThreadPool(2);
        executor.execute(new Customer());
        executor.execute(new Producer());

        executor.shutdown();
    }
}
